package com.ht.api.db.util;

import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import org.springframework.data.redis.core.RedisTemplate;

import cn.hutool.core.lang.TypeReference;
import cn.hutool.extra.spring.SpringUtil;

/**
 * Redis工具类（内部使用spring的RedisTemplate）
 * @author asq
 * @createTime 2024年12月21日 17:40:44
 */
public class RedisUtil {
	// 使用spring的RedisTemplate管理redis
	private static RedisTemplate<String, Object> redisTemplate = SpringUtil
			.getBean(new TypeReference<RedisTemplate<String, Object>>() {
			});

	/**
	 * 查询键过期时间
	 * @param key
	 * @return
	 */
	public static long getExpire(String key) {
		return redisTemplate.getExpire(key);
	}

	/**
	 * 设置键值
	 * @param <T>
	 * @param key
	 * @param value
	 */
	public static <T> void set(String key, T value) {
		redisTemplate.opsForValue().set(key, value);
	}

	/**
	 * 设置键值并指定过期时间（秒）
	 * @param <T>
	 * @param key
	 * @param value
	 * @param seconds
	 */
	public static <T> void set(String key, T value, long seconds) {
		redisTemplate.opsForValue().set(key, value, seconds, TimeUnit.SECONDS);
	}

	/**
	 * 设置键值并指定过期时间
	 * @param <T>
	 * @param key
	 * @param value
	 * @param timeout
	 * @param timeUnit
	 */
	public static <T> void set(String key, T value, long timeout, TimeUnit timeUnit) {
		redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
	}

	/**
	 * 批量写入键值（永久有效）
	 * @param <T>
	 * @param key
	 * @param value
	 */
	public static <T> void mset(Map<? extends String, ? extends Object> map) {
		redisTemplate.opsForValue().multiSet(map);
	}

	/**
	 * 获取键值
	 * @param <T>
	 * @param key
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T get(String key) {
		Object value = redisTemplate.opsForValue().get(key);
		return value != null ? (T) value : null;
	}

	/**
	 * 获取多个键值
	 * @param <T>
	 * @param keys 键名集合
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> List<T> mget(List<String> keys) {
		List<Object> values = redisTemplate.opsForValue().multiGet(keys);
		if (values == null) {
			return null;
		}
		return values.stream().map(value -> value != null ? (T) value : null).collect(Collectors.toList());
	}

	/**
	 * 设置hash键值
	 * @param <T>
	 * @param key
	 * @param hashKey
	 * @param value
	 */
	public static <T> void hset(String key, String hashKey, T value) {
		redisTemplate.opsForHash().put(key, hashKey, value);
	}

	/**
	 * 获取hash键值
	 * @param <T>
	 * @param key
	 * @param hashKey
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T hget(String key, String hashKey) {
		Object value = redisTemplate.opsForHash().get(key, hashKey);
		return value != null ? (T) value : null;
	}
	
	/**
	 * 返回hashset
	 * @param key
	 * @return
	 */
	public static Map<Object, Object> entries(String key) {
		Map<Object, Object> map = redisTemplate.opsForHash().entries(key);
		return map;
	}

	/**
	 * 更新一个键的过期时间
	 * @param key
	 * @param seconds
	 */
	public static void expire(String key, int seconds) {
		redisTemplate.expire(key, seconds, TimeUnit.SECONDS);
	}

	/**
	 * 设置一个键在指定时间过期
	 * @param key
	 * @param unixTimestamp
	 */
	public static void expireAt(String key, long unixTimestamp) {
		redisTemplate.expireAt(key, new Date(unixTimestamp));
	}

	/**
	 * 设置一个键在指定时间过期
	 * @param key
	 * @param unixTimestamp
	 */
	public static void expireAt(String key, Date date) {
		redisTemplate.expireAt(key, date);
	}

	/**
	 * 删除某个键
	 * @param key
	 */
	public static void delete(String key) {
		redisTemplate.delete(key);
	}

	/**
	 * 删除Hash 中的某些键
	 * @param key
	 */
	public static void delete(String key, Object... hashKeys) {
		redisTemplate.opsForHash().delete(key, hashKeys);
	}

	/**
	 * 删除多个键
	 * @param key
	 */
	public static void delete(Collection<String> keys) {
		redisTemplate.delete(keys);
	}

	/**
	 * 删除多个键
	 * @param key
	 */
	public static void delete(String... key) {
		redisTemplate.delete(Arrays.asList(key));
	}

	/**
	 * 检查某个键是否存在
	 * @param key
	 */
	public static boolean exists(String key) {
		return redisTemplate.hasKey(key);
	}
}
